import copy
import json
import os.path
import time
import requests
import tempfile
import jsonschema
from jsonschema import validate
from loguru import logger

import Connector.client as client
import Utils.command.CommandManager as Manager

import CloudEngine.Render.Application as App
import CloudEngine.Render.GyLoader as GyLoaderMod

import CloudEngine.core.VTActor as VTActorMod
from CloudEngine.core.LabelActor import LabelActor
from CloudEngine.core.SphereActor import SphereActor
from CloudEngine.core.PointCloudActor import PointCloudActor

from CloudEngine.IO.ElectromagnetismDataReader import ElectromagnetismDataReader
from CloudEngine.IO import IVTKReader
from CloudEngine.IO.IMshReader import IMshReader

from service.cmd.cmd_actor_color_reset import CmdActorColorReset
from service.cmd.cmd_app_actors_list import CmdAppActorsList
from service.cmd.cmd_attribute_get import CmdAttributeGet
from service.cmd.cmd_attribute_list import CmdAttributeList
from service.cmd.cmd_file_load import CmdFileLoad
from service.cmd.cmd_file_read import CmdFileRead
from service.cmd.cmd_fx_run import CmdFxRun
from service.cmd.cmd_geometry_create import CmdGeometryCreate
from service.cmd.cmd_mesh_features_search import CmdMeshFeaturesSearch
from service.cmd.cmd_mesh_list import CmdMeshList
from service.cmd.cmd_render_attribute import CmdRenderAttribute
from service.cmd.cmd_render_clear import CmdRenderClear
from service.cmd.cmd_render_highlight import CmdRenderHighlight
from service.cmd.cmd_render_highlight_reset import CmdRenderHighlightReset
from service.cmd.cmd_render_mode import CmdRenderMode
from service.cmd.cmd_render_show import CmdRenderShow
from service.cmd.cmd_topology_get import CmdTopologyGet
from service.cmd.cmd_view_resize import CmdViewResize
from service.func.file_load import file_load
from service.cmd.cmd_actor_attributes import CmdActorAttributes


def write_file(file_name, content):
    """
    将指定内容写入指定文件
    :param file_name: 文件名
    :param content: 文件内容
    """
    with open(file_name, "w") as f:
        f.write(content)


def read_file(file_name):
    """
    读取指定文件内容
    :param file_name: 文件名
    :return: 文件内容
    """
    with open(file_name, "r") as f:
        return f.read()


class Service:
    app: App.Application = App.Application()

    def __init__(self, queue, result_queue, other_process):
        self.CommandManager = Manager.ActorManager(self.app)
        # ~~~~ 华丽分割线 ~~~~
        self.app.queue = queue
        self.app.other_process = other_process
        self.app.result_queue = result_queue
        self.app.manager = self.CommandManager

    async def run(self):
        self.app.run()
        client.app = self.app
        # 信号处理回调
        client.callback = self.handle_command_message
        #  🔃 测试函数
        # self.test()
        # self.test_vtk()
        # self.load_all_binary_data_bin_file()
        # self.testSphere()
        # self.testLabel()
        # self.test_plane()
        # self.test_eb_dat()
        # self.test_cgns()
        # 连接服务器
        await client.connect_client("http://localhost:3000")
        await client.sio.wait()

    def test(self):
        # self.app.save_image()
        a = IMshReader()
        a.read("")
        # read_cgns(self)
        # read_vtu("C:/Users/Chris/Downloads/model.vtu")
        # read_vtp(self, {
        #     "path": "http://127.0.0.1:9000/d3-engine/model/diskout.vtp"
        # })

    def test_plane(self):
        a = time.time()
        content = read_file("box.json")
        total = 0
        for obj_str in json.loads(content):
            vertexes = []
            loader = GyLoaderMod.GyLoader(obj_str)
            tmp = copy.copy(loader.vertexes_map)
            for key, value in tmp.items():
                vertexes.append({"id": key, "XYZ": value})
            actor = VTActorMod.VTActor(
                loader.poly_data,
                {
                    "vertexes": vertexes,
                    "outlines": loader.edgeData,
                    # "color": [random.random(), random.random(), random.random(), 255],
                },
            )
            total = total + actor.total_triangles()
            actor.set_render_type("SURFACE")
            # actor.normals_on()
            self.app.add(actor)
        print("总的三角面数:", total, "耗时:", time.time() - a)
        self.app.d_render()

    def testLabel(self):
        label = LabelActor([0, 0, 0], {"text": "haha"})
        label.mount(self.app.renderer, 1080)
        self.model_add(label)

    def testSphere(self):
        sphere = SphereActor([0, 0, 0], {"radius": 0.1, "color": [0, 1, 0]})
        sphere.setVisible(True)
        self.model_add(sphere)

    def test_vtk(self):
        # self.file_load("C:\\Users\\Chris\\Downloads\\out\\out1.vtk", "vtk")
        # self.file_load("C:\\Users\\Chris\\Downloads\\stp_demo\\office.binary.vtk", "vtk", {"file_type": "dataset"})
        # file_load(self,
        #           {
        #               "url": "C:\\Users\\Chris\\Downloads\\case1.vtk",
        #               "type": "vtk",
        #               "DataType": "dataset",
        #               "ParseAttributes": True
        #           });
        file_load(
            self,
            {
                "url": r"/Users/vvvvv1n/Desktop/sh/case1.vtk",
                "type": "vtk",
                "DataType": "dataset",
                "ParseAttributes": True,
                "ColorType": "erdc_rainbow_bright",
                "ColorLevels": 256,
                "IsVector": True,
            },
        )

        scalars = self.app.actorList.value()[0].attributes["displacement"].dy
        self.app.actorList.value()[0].scalar_bar_on(scalars)
        self.app.render_at_once()

    def test_eb_dat(self):
        self.read_eb_data(
            "C:\\Users\\Chris\\Downloads\\stp_demo\\dc_back_processing.dat"
        )
        # self.app.render_with_desktop()

    def test_cgns(self):
        # cgns_reader = ICgnsReader()
        # cgns_reader.read("C:/Users/Chris/Downloads/stp_demo/cgns/meanflow.cgns")
        # write_file("./out.json", cgns_reader.to_json())
        file_load(
            self,
            {
                "path": "http://10.13.13.182:30002/d3-engine/model/meanflow.cgns",
                "FileType": "cgns",
            },
        )

    def read_vtk(self, url, file_type, options={}):
        reader_instance = IVTKReader.IVTKReader(options.get("DataType"))
        reader_instance.read(url)
        if options.get("DataType") == "dataset":
            poly_data = reader_instance.output()
            actor = VTActorMod.VTActor(poly_data, {"parse_attributes": True})
            self.model_add(actor)

    def get_template_path(self, url, type):
        response = requests.get(url, stream=True)
        tf = tempfile.mktemp(suffix="." + type, dir="./")
        tf_abs = os.path.abspath(tf)
        with open(tf_abs, "wb") as f:
            for chunk in response.iter_content(chunk_size=8192):
                if chunk:
                    f.write(chunk)
        print(tf_abs, "tf")
        return tf_abs

    def cleanup_temp_file(self, file_path):
        try:
            os.remove(file_path)
            print(f"Temporary file {file_path} deleted.")
        except OSError as e:
            print(f"Error deleting temporary file {file_path}: {e}")

    def model_add(self, actor):
        self.app.add(actor)

    # 📦 处理收到的指令
    async def handle_command_message(self, message):
        logger.info(message)
        Topic = message.get("Topic")
        if Topic != "command":
            return
        Type = message.get("Type")
        Params = message.get("Params")
        Tag = message.get("Tag")
        match Type:
            case "cmd.file.load":
                await CmdFileLoad(self, Params, Tag, Type).execute()
            case "cmd.mesh.load":
                print("todo")
            case "cmd.mesh.create":
                print("todo")
            case "cmd.actors.list":  # 返回场景中所有的actor列表
                await CmdAppActorsList(self, Params, Tag, Type).execute()
            case "cmd.actor.attributes":
                await CmdActorAttributes(self, Params, Tag, Type).execute()
            case "cmd.file.read":
                await CmdFileRead(self, Params, Tag, Type).execute()
            case "cmd.mesh.features.search":
                await CmdMeshFeaturesSearch(self, Params, Tag, Type).execute()
            case "cmd.view.resize":
                await CmdViewResize(self, Params, Tag, Type).execute()
            case "cmd.attribute.list":
                await CmdAttributeList(self, Params, Tag, Type).execute()
            case "cmd.render.attribute":
                await CmdRenderAttribute(self, Params, Tag, Type).execute()
            case "cmd.topology.get":
                await CmdTopologyGet(self, Params, Tag, Type).execute()
            case "cmd.attribute.get":
                await CmdAttributeGet(self, Params, Tag, Type).execute()
            case "cmd.render.mode":
                await CmdRenderMode(self, Params, Tag, Type).execute()
            case "cmd.render.clear":
                await CmdRenderClear(self, Params, Tag, Type).execute()
            case "cmd.actor.color.reset":
                await CmdActorColorReset(self, Params, Tag, Type).execute()
            case "cmd.render.highlight":
                await CmdRenderHighlight(self, Params, Tag, Type).execute()
            case "cmd.render.highlight.reset":
                await CmdRenderHighlightReset(self, Params, Tag, Type).execute()
            case "cmd.mesh.list":
                await CmdMeshList(self, Params, Tag, Type).execute()
            case "cmd.render.show":
                await CmdRenderShow(self, Params, Tag, Type).execute()
            case "cmd.geometry.create":
                await CmdGeometryCreate(self, Params, Tag, Type).execute()
            case "cmd.fx.run":
                await CmdFxRun(self, Params, Tag, Type).execute()

    # 📦 上航电磁学后处理文件
    def read_eb_data(self, file_path, is_remote=False):
        reader = ElectromagnetismDataReader()
        if is_remote:
            reader.read_from_remote(file_path)
        else:
            reader.read(file_path)
        actor = PointCloudActor(reader.get_poly_data(), reader.get_scalar_range())
        self.app.add(actor)
        self.app.renderer.ResetCamera()

    # 📦 获取第一个actor
    def get_first_actor(self):
        if self.app.actorList.size() > 0:
            return self.app.actorList.value()[0]
        return None

    # 📦 获取第二个actor 约定为线对象
    def get_second_actor(self):
        if self.app.actorList.size() > 1:
            return self.app.actorList.value()[1]
        return None

    # 📦 获取第二个actor 约定为3d对象
    def get_third_actor(self):
        if self.app.actorList.size() > 2:
            return self.app.actorList.value()[2]
        return None

    # 📦 渲染
    def render(self):
        self.app.render()
